﻿using Ocelot.Configuration;
using Ocelot.Configuration.Repository;
using Ocelot.Responses;
using System;
using System.Collections.Generic;
using System.Text;
using Naruto.Redis.IRedisManage;
using Newtonsoft.Json;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Configuration.Creator;
using Naruto.Redis;
using Ocelot.Configuration.File;

namespace Naruto.OcelotStore.RedisProvider
{
    /// <summary>
    /// 张海波
    /// 2019-08-16
    /// 重写内部的基本配置的仓储(网关的每次的调用都会触发当前类 来获取路由的信息)
    /// 用单例注册
    /// </summary>
    public class RedisInternalConfigurationRepository : IInternalConfigurationRepository
    {

        private static readonly object LockObject = new object();
        /// <summary>
        /// 获取redis对象
        /// </summary>
        private IRedisRepository redis;

        /// <summary>
        /// 存储到redis的缓存key
        /// </summary>
        private readonly string RedisCacheKey = "Ocelot:InternalConfiguration";

        private IServiceProvider serviceProvider;

        private readonly IInternalConfigurationCreator configCreator;

        public RedisInternalConfigurationRepository(IRedisRepository _redis, IServiceProvider _serviceProvider, IInternalConfigurationCreator _configCreator)
        {
            redis = _redis;
            serviceProvider = _serviceProvider;
            configCreator = _configCreator;
        }

        /// <summary>
        /// 将数据替换掉
        /// </summary>
        /// <param name="internalConfiguration"></param>
        /// <returns></returns>
        public Response AddOrReplace(IInternalConfiguration internalConfiguration)
        {
            //由于从 ocleot14.0.4版本开始 RateLimitOptions 实体构造函数中的 getClientWhitelist 改为传递委托的方式进行动态构造
            //此时无法解决 反序列化 InternalConfiguration的json对象时导致getClientWhitelist委托为空导致系统报错
            //所以将不再存储InternalConfiguration 到缓存中 改成将FileConfiguration 存储到缓存中
            //直到找到问题的解决方式
            //lock (LockObject)
            //{
            //    //存储基本的配置
            //    redis.String.Add(RedisCacheKey, internalConfiguration);
            //}
            return new OkResponse();
        }
        /// <summary>
        /// 获取配置的基本信息
        /// </summary>
        /// <returns></returns>
        public Response<IInternalConfiguration> Get()
        {
            IInternalConfiguration internalConfiguration = default;
            lock (LockObject)
            {
                //获取基本的配置
                var fileCig = redis.String.Get<FileConfiguration>(RedisCacheKey);
                if (fileCig == null)
                {
                    //获取所有配置服务的仓储
                    var fileConfigRepository = serviceProvider.GetService<IFileConfigurationRepository>();
                    //重新设置缓存
                    fileCig = fileConfigRepository.Get().GetAwaiter().GetResult().Data;
                    //存储基本配置
                    redis.String.Add(RedisCacheKey, fileCig);
                }
                //获取创建配置的服务(创建一个基本的配置数据 包含路由等数据)
                internalConfiguration = configCreator.Create(fileCig).GetAwaiter().GetResult().Data;
                return new OkResponse<IInternalConfiguration>(internalConfiguration);
            }
        }
    }
    ///// <summary>
    ///// 张海波
    ///// 2019-08-16
    ///// 重写内部的基本配置的仓储(网关的每次的调用都会触发当前类 来获取路由的信息)
    ///// 用单例注册
    ///// </summary>
    //public class RedisInternalConfigurationRepository : IInternalConfigurationRepository
    //{

    //    private static readonly object LockObject = new object();
    //    /// <summary>
    //    /// 获取redis对象
    //    /// </summary>
    //    private IRedisRepository redis;

    //    /// <summary>
    //    /// 存储到redis的缓存key
    //    /// </summary>
    //    private readonly string RedisCacheKey = "Ocelot:InternalConfiguration";

    //    private IServiceProvider serviceProvider;

    //    public RedisInternalConfigurationRepository(IRedisRepository _redis, IServiceProvider _serviceProvider)
    //    {
    //        redis = _redis;
    //        serviceProvider = _serviceProvider;
    //    }

    //    /// <summary>
    //    /// 将数据替换掉
    //    /// </summary>
    //    /// <param name="internalConfiguration"></param>
    //    /// <returns></returns>
    //    public Response AddOrReplace(IInternalConfiguration internalConfiguration)
    //    {
    //        lock (LockObject)
    //        {
    //            //存储基本的配置
    //            redis.String().Add(RedisCacheKey, internalConfiguration);
    //        }
    //        return new OkResponse();
    //    }
    //    /// <summary>
    //    /// 获取配置的基本信息
    //    /// </summary>
    //    /// <returns></returns>
    //    public Response<IInternalConfiguration> Get()
    //    {
    //        //InternalConfiguration
    //        lock (LockObject)
    //        {
    //            //获取基本的配置
    //            var internalConfiguration = redis.String().Get<InternalConfiguration>(RedisCacheKey);

    //            if (internalConfiguration == null)
    //            {
    //                //获取所有配置服务的仓储
    //                var fileConfigRepository = serviceProvider.GetService<IFileConfigurationRepository>();
    //                //获取创建配置的服务(创建一个基本的配置数据 包含路由等数据)
    //                var configCreator = serviceProvider.GetService<IInternalConfigurationCreator>();
    //                //重新设置缓存
    //                AddOrReplace(configCreator.Create(fileConfigRepository.Get().GetAwaiter().GetResult().Data).GetAwaiter().GetResult().Data);

    //                //重新获取数据
    //                internalConfiguration = redis.String().Get<InternalConfiguration>(RedisCacheKey);
    //            }

    //            return new OkResponse<IInternalConfiguration>(internalConfiguration);
    //        }
    //    }
    //}
}
